using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using System.Threading;

namespace Komodex.NETMF.TweetingBreathalyzer.Helpers
{
    public class RGBLED
    {
        protected readonly PWM redPWM, greenPWM, bluePWM;
        protected readonly PWM[] allPWMColors;
        protected readonly bool invertedOutput;

        public RGBLED(Cpu.Pin redPin, Cpu.Pin greenPin, Cpu.Pin bluePin, bool invertOutput = false)
        {
            invertedOutput = invertOutput;

            redPWM = new PWM(redPin);
            greenPWM = new PWM(greenPin);
            bluePWM = new PWM(bluePin);
            allPWMColors = new PWM[] { redPWM, greenPWM, bluePWM };

            // Turn off all LED colors
            SetColor(0, 0, 0);
        }

        #region Public Methods

        public void SetColor(int red, int green, int blue)
        {
            if (red >= 0)
                redPWM.SetDutyCycle(AdjustedValue(red));
            if (green >= 0)
                greenPWM.SetDutyCycle(AdjustedValue(green));
            if (blue >= 0)
                bluePWM.SetDutyCycle(AdjustedValue(blue));
        }

        public void SetTwoColorRange(RGB lowColor, RGB highColor, int value)
        {
            PWM low = allPWMColors[(int)lowColor];
            PWM high = allPWMColors[(int)highColor];

            if (value > 100)
                value = 100;
            if (value < 0)
                value = 0;

            uint adjustedValue = AdjustedValue(value);

            low.SetDutyCycle(100 - adjustedValue);
            high.SetDutyCycle(adjustedValue);
        }

        public void FullSweep(RGB fromColor, RGB toColor, int stepDelay = 10)
        {
            PWM from = allPWMColors[(int)fromColor];
            PWM to = allPWMColors[(int)toColor];

            for (int i = 0; i <= 100; i++)
            {
                uint adjustedValue = AdjustedValue(i);
                from.SetDutyCycle(100 - adjustedValue);
                to.SetDutyCycle(adjustedValue);
                Thread.Sleep(stepDelay);
            }
        }

        #endregion

        #region Private Helper Methods

        protected uint AdjustedValue(int value)
        {
            return AdjustedValue((uint)value);
        }

        protected uint AdjustedValue(uint value)
        {
            if (invertedOutput)
                return 100 - value;
            return value;
        }

        #endregion
    }

    public enum RGB
    {
        Red = 0,
        Green = 1,
        Blue = 2
    }
}
